<template>
  <div id="app" v-loading="loading" :class="{ 'dark-mode': themeMode === 'dark' }">
    <el-container>
      <el-header>
        <div>
          <div class="des">
            <div class="msg" v-for="(item, index) in msgList" :key="index">
              <span v-if="index<2">{{item.label+' : '+item.value + ' ' + item.unit}}</span>
              <span v-else style="display:flex">{{item.label+' : '}} 
                <p v-show="speedFlag">{{item.value + ' ' + item.unit}}</p>
                <i style="marginLeft:5px" class="el-icon-view" @click="speedFlag=!speedFlag"></i>
              </span>
            </div>
          </div>
          <el-switch
            v-model="themeMode"
            active-value="dark"
            inactive-value="light"
            active-text="dark"
            inactive-text="light"
            style="margin-right: 10px"
            @change="val => $store.commit('change', val)"
          ></el-switch>
          <el-tooltip class="item" effect="light" content="upload to cloud" placement="bottom" >
            <el-button
              icon="el-icon-upload"
              @click="handleSaveToCloud"
            ></el-button>
          </el-tooltip>
          <el-tooltip class="item" effect="light" content="import layout config" placement="bottom" >
            <el-button
              icon="el-icon-upload2"
              @click="configVisible = true"
              />
          </el-tooltip>
          <el-tooltip class="item" effect="light" content="download layout config" placement="bottom" >
            <el-button
              icon="el-icon-download"
              @click="onExport"
            ></el-button>
          </el-tooltip>
          <el-tooltip class="item" effect="light" content="layout setting" placement="bottom" >
            <el-button
              type="primary"
              icon="el-icon-setting"
              @click="layoutVisible = true"
            ></el-button>
          </el-tooltip>
        </div>
      </el-header>
      <div class="main-contain">
        <el-main>
          <el-row>
            <el-col v-if="grid.constVisible" :span="24">
              <const-panel style="height: 100px;box-sizing: border-box"></const-panel>
            </el-col>
            <el-col v-if="gridVisible" :span="grid.signalVisible ? 20 : 24">
              <el-row v-for="(item, index) in grid.layout" :key="index" :gutter="10">
                <el-col v-for="(graph, i) in item" :key="index + '-' + i" :span="24 / item.length">
                  <graph
                    :ref="index+'-'+i"
                    :style="graphStyle"
                    :vin="vin"
                    :tripid="tripid"
                    :graph="filterSignals(graph)"
                    :index="i"
                    :graph-key="index + '-' + i"
                    :disabled-right="i === item.length - 1"
                    @move="(type) => move(index, i, type)"
                    @change="val => handleGraphChange(val, index, i)"
                    @changeData="getGraph"
                    @clickData="getClickData"
                  />
                </el-col>
              </el-row>
            </el-col>
            <el-col v-if="grid.signalVisible" :span="4">
              <signal-panel />
            </el-col>
          </el-row>
        </el-main>
        <div class="bottom">
          <div class="buttonBox">
            <el-button class="buttonText" @click="setting" type="text">Setting</el-button>
            <el-button class="button"
              type="primary"
              :icon="status ? 'el-icon-arrow-right' : 'el-icon-arrow-left'"
              @click="openAndClose"
            ></el-button>
          </div>

          <div class="bottomScroll" :class="{ open: status === true }">
            <div class="bottomBox" v-for="(item, index) in bottomData" :key="index">
              <span class="text">{{ item.text }}</span>
              <span class="value">{{ item.value }}{{ item.value2 }}{{ item.unit }}</span>
            </div>
          </div>
        </div>
      </div>
    </el-container>
    <config-dialog
      :visible.sync="configVisible"
      @import="onImport"
    ></config-dialog>
    <layout-dialog
      :visible.sync="layoutVisible"
      :grid="grid.layout"
      :const-visible="grid.constVisible"
      :signal-visible="grid.signalVisible"
      @save="onLayoutSave"
    ></layout-dialog>
    <signal-dialog
      :visible.sync="signalVisible"
      :checked="bottomData.map((v) => v.key)"
      @save="onSignalSave"
    ></signal-dialog>
  </div>
</template>

<script>
import Graph from '@/components/Graph'
import ConfigDialog from '@/components/ConfigDialog'
import LayoutDialog from '@/components/LayoutDialog'
import SignalPanel from "@/components/SignalPanel";
import ConstPanel from "@/components/ConstPanel";
import "moment-duration-format"
import { getSignalList, getGraphData, getBottomData, getSetting, saveSetting } from '@/api'
import { getQueryString } from '@/utils'
import _, { isArray } from 'lodash'
import { blobDownLoad } from '@/utils'
import { List } from 'echarts'
import SignalDialog from '@/components/SignalDialog'
import moment from 'moment-timezone'

class Layout{
  constructor() {
    this.name = null
    this.graphtype = "1"
    this.graphx = null
    this.graphy = null
    this.plotsampling = 3
    this.datecolmn = []
    this.sort = null
    this.xAxisTick = 1
    this.width = 2
  }
}

export default {
  name: 'App',
  components: {
    Graph,
    ConfigDialog,
    LayoutDialog,
    SignalPanel,
    ConstPanel,
    SignalDialog
  },
  data() {
    return {
      overviewType: "line",
      options: {},
      start:null,
      startTime:null,
      graph: [],
      msgList: [
        { label: "ODO", value: "", unit: "Km" },
        { label: "GENERATION TIME", value: "", unit: "Hours" },
        { label: "SPEED", value: "", unit: "km/h" },
      ],
      speedFlag:false,
      sendingTime:"",
      status: true,
      vin: "",
      configVisible: false,
      layoutVisible: false,
      grid: {
        layout: [],
        constVisible: false,
        signalVisible: false
      },
      graphStyle: {
        width: "100%",
        height: "600px"
      },
      bottomSetting: [], //下方初始数据
      bottomData: [], //下方渲染数据
      signalVisible: false, //下方的settings
      gridVisible: false, // 主页面
      loading: false,
      tripid: null,
      themeMode: "dark"
    }
  },
  computed: {
    signals() {
      return this.$store.state.signals
    }
  },
  created() {
    this.loading = true
    // 历史行程进入 ?vin=xxx&tripid=xxx
    // 实时行程进入 ?vin=xxx
    const vin = getQueryString("vin")
    const tripid = getQueryString("tripid")
    this.vin = vin
    this.tripid = tripid
  },
  async mounted() {
    await this.getSignalList()
    await this.getSetting()
  },
  methods: {
    handleGraphChange(data, index, i) {
      const row = _.clone(this.grid.layout[index])
      row[i] = data
      this.grid.layout.splice(index, 1, row)
    },
    getGraph(data) {
      this.bottomData = this.bottomData.map((item) => {
        return { ...item, value: data[item.key] || '' }
      })
      this.startTime=data.startTime
      this.sendingTime=data.sendingtime
      this.msgList[0].value = data.nowmileage;
      this.msgList[1].value = data.nowgentime;
      this.msgList[2].value = data.nowspeed;
      this.getBottonData(data.flag);
    },
    getClickData(data){
     //点击图表获取来的X轴的值
      this.sendingTime=data.data // data为当前点击的点的时间
      this.start=data.start // 当前图表的第一条数据
      this.getBottonData(false);
    },
    filterSignals(graph) {
      if (graph.datecolmn.length) {
        return {
          ...graph,
          datecolmn: graph.datecolmn.filter(v => this.signals.find(k => k.column === v.key) !== undefined)
        }
      } else {
        return graph
      }
    },
    async getSignalList() {
      const response = await getSignalList()
      this.$store.commit("initSignal", Object.freeze(_.unionBy(response.data[0].children, "name")))
    },
    async getSetting() {
      const res = await getSetting()
      const { layout, bottomConfig, constVisible = false, signalVisible = false } = res.data
      this.grid = {
        layout: isArray(layout) && layout.length ? layout : [],
        constVisible,
        signalVisible
      }
      if (bottomConfig && bottomConfig.length) {
        this.bottomSetting = bottomConfig;
        const array = [];
        bottomConfig.forEach(item => {
          this.signals.forEach(it => {
            if (item === it.column) {
              array.push({ key: it.column, text: it.name, unit: it.unit });
            }
          });
        });
        this.bottomData = array;
      }
      await this.initHeight(this.grid.layout, constVisible)
      this.gridVisible = true
      this.loading = false
    },
    async initHeight(layout, constVisible = false) {
      const app = document.getElementById("app").offsetHeight
      const mainHeight = app - 60 - 10 - (constVisible ? 100 : 0) - 110
      const graphHeight = mainHeight / layout.length
      this.graphStyle.height = `${graphHeight}px`
    },
    async onLayoutSave(data) {
      // todo 如果 firstRow 和 secondRow 没有发生变化，不应重新赋值
      this.gridVisible = false
      const { firstRow, secondRow, constVisible, signalVisible } = data
      const lay = new Layout()
      // const firstArr = new Array(firstRow).fill(lay)
      const firstArr = []
      for(let i = 0; i < firstRow; i++) {
        firstArr.push(lay)
      }
      const layout = _.cloneDeep(this.grid.layout)
      const first = layout[0] ? layout[0].splice(0, firstRow) : []
      firstArr.forEach((v, i) => {
        if (!first[i]) {
          first.push(v)
        }
      })
      let second = []
      if (layout.length === 2 && secondRow) {
        second = layout[1] ? layout[1].splice(0, secondRow) : []
        const secondArr = new Array(secondRow).fill(new Layout())
        secondArr.forEach((v, i) => {
          if (!second[i]) {
            second.push(v)
          }
        })
      } else if (secondRow) {
        const secondArr = new Array(secondRow).fill(new Layout())
        secondArr.forEach((v, i) => {
          if (!second[i]) {
            second.push(v)
          }
        })
      }
      this.grid.layout = second.length ? [first, second] : [first]
      this.grid.constVisible = constVisible
      this.grid.signalVisible = signalVisible
      await this.initHeight(this.grid.layout, constVisible)
      await this.$nextTick()
      this.gridVisible = true
    },
    onGridSave() {
      const config = this.grid.layout.map((row, index) => {
        return row.map((v, i) => {
          return this.$refs[`${index}-${i}`][0].setting
        })
      })
      const str = JSON.stringify(_.cloneDeep({ layout: config, bottomConfig: this.bottomSetting }))
      saveSetting({ setting: str })
        .then(res => {
          if(res.data === 1) {
            this.$message.success("success")
          }
        })
    },
    move(rowIndex, columnIndex, type) {
      this.gridVisible = false
      let flag = type === "right" ? 1 : -1
      const row = _.cloneDeep(this.grid.layout[rowIndex])
      const left = row[columnIndex]
      const right = row[columnIndex + flag]
      row.splice(columnIndex, 1, right)
      row.splice(columnIndex + flag, 1, left)
      this.grid.layout.splice(rowIndex, 1, row)
      this.$nextTick(() => {
        this.gridVisible = true
      });
    },
    onImport(config) {
      this.gridVisible = false
      this.loading = true
      setTimeout(() => {
        this.grid = { layout: config.layout }
        this.bottomSetting = config.bottomConfig?config.bottomConfig:[];
        this.getBottonData(true)
        this.initHeight(this.grid.layout)
        this.gridVisible = true
        this.loading = false
      }, 1000)

    },
    onExport() {
      this.$alert("Are you sure to export?", "Hint", { confirmButtonText: "Confirm", callback: (action) => {
        const config = this.grid.layout.map((row, index) => {
          return row.map((v, i) => {
            return this.$refs[`${index}-${i}`][0].setting
          })
        })
        const str = JSON.stringify(_.cloneDeep({ layout: config, bottomConfig: this.bottomSetting }))
        blobDownLoad(str,"layout.json")
      }})
    },
    handleSaveToCloud() {
      this.$confirm('This action will save layout config to the cloud, continue?', 'Notice', {
          confirmButtonText: 'confirm',
          cancelButtonText: "cancel",
          type: 'warning'
        }).then(() => {
          this.onGridSave()
        }).catch(() => {});
    },
    openAndClose() {
      this.status = !this.status;
    },
    setting() {
      this.signalVisible = true;
    },
    onSignalSave(data) {
      this.bottomSetting = data;
      this.getBottonData(true);
    },
    async getBottonData(flag) {
      //flag用来判断是否是初次进入页面，是初次不+3600000
      let now=new Date()
      var currentTimezone = moment(now).utcOffset();
      // console.log(this.sendingTime,"this.sendingTime")
      // const sendingTime=currentTimezone===540&&!flag?Number(this.sendingTime)+3600000:this.sendingTime//判断时区是否是日本，是日本且不是初次加载加一小时，不是日本且是初次进入获取最后一条获取当前时间
      // console.log(sendingTime,"this.sendingTime")159000
      if(flag){
        //是初次进入，或车辆未结束的轮训获取来的数据
        var  sendingTime=this.sendingTime
      }else{
        var sendingTime=currentTimezone===540?Number(this.sendingTime)+3600000:this.sendingTime
      }
      const time=Number(this.sendingTime)+this.start//startTime为什么要加？

      const res=await getBottomData({
        vin: this.vin,
        keys: this.bottomSetting.join(","),
        sendingTime:this.sendingTime.toString().length===13?sendingTime:time.toString(),//等于13为绝对时间，不等于为相对时间：318000，相对时间需要加3600000
      })
      const array = [];
      this.bottomSetting.forEach((item) => {
        this.signals.forEach((it) => {
          if (item === it.column) {
            array.push({ key: it.column, text: it.name, unit: it.unit });
          }
        })
      });
      this.bottomData = array.map((item) => {
        if (res.data[item.key]) {
          return { ...item, value: res.data[item.key] };
        } else {
          return { ...item, value: "" };
        }
      })
    }
  }
}
</script>

<style lang="scss">
#app{
  height: 100vh;
}
.el-container{
  height: 100vh;
  .el-header{
    border-bottom: 1px solid #dcdfe6;
    display: flex;
    align-items: center;
    flex-direction: row-reverse;
    div {
      display: flex;
      align-items: center;
      justify-content: right;
      .des {
        margin-right: 20px;
        display: flex;
        align-items: center;
        justify-content: left !important;
        .msg {
          // flex: 1;
          margin-right: 15px;
          // width:190px;
          height: 100%;
          white-space: nowrap;
        }
      }
    }
  }
  .main-contain {
    .el-main{
      padding: 5px;
      float: left;
      width: 100%;
      height: calc(100vh - 165px);
      .el-row{
        margin-left: 0!important;
        margin-right: 0!important;
        .el-col{
          padding-left: 0!important;
          padding-right: 0!important;
          .graph-container{
            border-right: 0;
          }
          &:last-child{
            .graph-container{
              border-right: 1px solid #8e8b8b;
            }
          }
        }
      }
    }
    .bottom {
      height: 100px;
      float: left;
      width: 100%;
      display: flex;
      .buttonBox {
        width: 50px;
        margin-left: 10px;
        .buttonText {
          padding: 2px 0px;
        }
        .button {
          width: 20px;
          padding: 30px 3px;
          // background: ;
        }
      }

      .bottomScroll {
        width: 0px;
        transition: width 0.3s ease;
        animation-fill-mode: forwards;
        overflow-x: scroll;
        overflow-y: hidden;
        white-space: nowrap;
        margin-left: 7px;
        margin-top: 7px;
        .bottomBox {
          display: inline-table;
          width: 300px;
          height: 70px;
          border: 1px solid #5d5f64;
          border-radius: 10px;
          margin-right: 20px;
          padding: 10px;
          .text {
            font-size: 20px;
            width: 100%;
            display: block;
          }
          .value {
            font-size: 28px;
            width: 100%;
            margin-top: 4%;
            text-align: right;
            display: block;
          }
        }
      }
      .open {
        width: 99%;
      }
    }
  }
}
.dark-mode {
  background-color: #100c2a;
  .el-loading-mask{
    background-color: rgba(6, 5, 16, 0.4);
  }
  .el-header{
    border-bottom: 1px solid #4C4D4F;
    .el-switch__label.el-switch__label--left{
      color: #E5EAF3;
    }
    .el-button{
      background-color: #100c2a;
      border: 1px solid #4C4D4F;
      color: #5d5f64;
      color: #ebebeb;
    }
    div {
      display: flex;
      align-items: center;
      justify-content: right;
      .des {
        margin-right: 20px;
        display: flex;
        align-items: center;
        justify-content: left !important;
        .msg {
          // flex: 1;
          margin-right: 15px;
          // width:190px;
          height: 100%;
          color: #e5eaf3;

          white-space: nowrap;
        }
      }
    }
  }
  .el-main{
    .el-row{
      .el-col{
        &:last-child{
          .graph-container{
            border-right: 1px solid #4C4D4F;
          }
        }
      }
    }
  }
  .bottom {
    // width: calc(100% - 200px);
    // height: 195px;
    height: 90px;
    float: left;
    width: 100%;
    .buttonBox {
      .buttonText {
        color: #ee6666;
      }
      .button {
        background: #ee6666;
        border: none;
      }
    }
    .bottomScroll {
      width: 99%;
      overflow-x: scroll;
      white-space: nowrap;
      margin-left: 7px;
      margin-top: 7px;
      .bottomBox {
        display: inline-table;
        width: 300px;
        height: 155px;
        border: 1px solid #8e8b8b;
        border-radius: 10px;
        margin-right: 20px;

        padding: 10px;
        .text {
          font-size: 20px;
          width: 100%;
          display: block;
          color: #ebebeb;
        }
        .value {
          font-size: 28px;
          width: 100%;
          margin-top: 21%;
          text-align: right;
          display: block;
          color: #ebebeb;
        }
      }
    }
  }
}
</style>
